package com.logic.service.impl;

import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Named;

import org.primefaces.model.chart.Axis;
import org.primefaces.model.chart.AxisType;
import org.primefaces.model.chart.BarChartModel;
import org.primefaces.model.chart.CartesianChartModel;
import org.primefaces.model.chart.CategoryAxis;
import org.primefaces.model.chart.ChartSeries;
import org.primefaces.model.chart.LineChartModel;
import org.primefaces.model.chart.LineChartSeries;

import com.database.bean.Agent;
import com.database.bean.Game;
import com.database.bean.News;
import com.database.bean.Product;
import com.database.bean.Report;
import com.database.bean.Round;
import com.database.bean.Setting;
import com.database.bean.Supplier;
import com.logic.service.AdminService;
import com.math.util.CalculationUtil;
import com.math.util.InitializationBean;
import com.math.util.StatisticBean;

@Named
public class AdminServiceImpl extends BaseServiceImpl implements Serializable, AdminService {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@Override
	public List<Game> getAllGames() {
		List<Game> allGames=gameDao.getAll();
		logger.debug("Returned all Games:"+allGames.size());
		return allGames;
	}

	@Override
	public BarChartModel getMarketGameBudgetChart(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameFirmData(game);
		BarChartModel model = null;	
		
		if(results.size()>0){
			model=new BarChartModel();
			for(StatisticBean result : results){
				ChartSeries budget = new ChartSeries();
		        budget.setLabel(result.getCompany_nickname());
		        budget.set("",result.getCompany_budget());
		        model.addSeries(budget);
			}
			
			model.setTitle("Budgets");
			model.setLegendPosition("ne");
	         
	        Axis xAxis = model.getAxis(AxisType.X);
	        xAxis.setLabel("");
	         
	        Axis yAxis = model.getAxis(AxisType.Y);
	        yAxis.setLabel("Money");
	        //yAxis.setMin(0);
	        //yAxis.setMax(200);
		}
		
		return model;
	}
	
	
	@Override
	public BarChartModel getMarketGameImageChart(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameFirmData(game);
		BarChartModel model = null;	
		
		if(results.size()>0){
			model=new BarChartModel();
			for(StatisticBean result : results){
				ChartSeries budget = new ChartSeries();
		        budget.setLabel(result.getCompany_nickname());
		        budget.set("",result.getCompany_imageValue());
		        model.addSeries(budget);
			}
			
			model.setTitle("Image");
			model.setLegendPosition("ne");
	         
	        Axis xAxis = model.getAxis(AxisType.X);
	        xAxis.setLabel("");
	         
	        Axis yAxis = model.getAxis(AxisType.Y);
	        yAxis.setLabel("");
	        yAxis.setMin(0);
	        yAxis.setMax(1.0);
		}
		
		return model;
	}

	@Override
	public BarChartModel getMarketGameTopSellingsChart(Game game,int top) {
		List<StatisticBean> results=statisticDao.getMarketGameSellings(game);
		BarChartModel model = null;
		
		int i=1;
		
		if(results.size()>0){
			model=new BarChartModel();
			
			for(StatisticBean result : results){
				if(i>top)
					break;
				
				ChartSeries budget = new ChartSeries();
		        budget.setLabel(result.getProduct_name() +" for "+result.getCompprod_sellingPrice() +" from "+result.getCompany_nickname());
		        budget.set("",result.getCompprod_amountSold());
		        model.addSeries(budget);
		        
		        i++;
			}
			
			model.setTitle("Top "+top+" Sellers in the Game");
			model.setLegendPosition("ne");
	         
	        Axis xAxis = model.getAxis(AxisType.X);
	        xAxis.setLabel("");
	         
	        Axis yAxis = model.getAxis(AxisType.Y);
	        yAxis.setLabel("");
	        //yAxis.setMin(0);
	        //yAxis.setMax(1.0);
		}
		return model;
	}

	@Override
	public LineChartModel getMarketGameRoundDecisionRevenue(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameRoundDecisionData(game);
		LineChartModel model = null;
		Map<String,ChartSeries> map=new HashMap<String,ChartSeries>();
		
		if(results.size()>0){
			model=new LineChartModel();
			for(StatisticBean result : results){
				if(map.containsKey(result.getCompany_nickname())){
					ChartSeries firm=map.get(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_revenue());
				}else{
					ChartSeries firm = new ChartSeries();
					firm.setLabel(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_revenue());
			        map.put(result.getCompany_nickname(), firm);model.addSeries(firm);
			        
				}
			}
			
			model.setTitle("Revenue Development");
			model.setLegendPosition("e");
			model.setShowPointLabels(true);
			model.getAxes().put(AxisType.X, new CategoryAxis("Rounds"));
			Axis yAxis = model.getAxis(AxisType.Y);
		    yAxis.setLabel("Money");
	        //Axis yAxis = model.getAxis(AxisType.Y);
	        //yAxis.setMin(0);
	        //yAxis.setMax(10);
		}
		
		return model;
	}
	
	@Override
	public LineChartModel getMarketGameRoundDecisionBudget(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameRoundDecisionData(game);
		LineChartModel model = null;
		Map<String,ChartSeries> map=new HashMap<String,ChartSeries>();
		
		if(results.size()>0){
			model=new LineChartModel();
			for(StatisticBean result : results){
				if(map.containsKey(result.getCompany_nickname())){
					ChartSeries firm=map.get(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_newBudget());
				}else{
					ChartSeries firm = new ChartSeries();
					firm.setLabel(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_newBudget());
			        map.put(result.getCompany_nickname(), firm);model.addSeries(firm);
			        
				}
			}
			
			model.setTitle("Budget Development");
			model.setLegendPosition("e");
			model.setShowPointLabels(true);
			model.getAxes().put(AxisType.X, new CategoryAxis("Rounds"));
			Axis yAxis = model.getAxis(AxisType.Y);
		    yAxis.setLabel("Money");
	        //Axis yAxis = model.getAxis(AxisType.Y);
	        //yAxis.setMin(0);
	        //yAxis.setMax(10);
		}
		
		return model;
	}
	
	@Override
	public LineChartModel getMarketGameImageDevelopment(Game game,Setting setting) {
		List<StatisticBean> results=statisticDao.getMarketGameRoundDecisionData(game);
		LineChartModel model = null;
		Map<String,ChartSeries> map=new HashMap<String,ChartSeries>();
		
		if(results.size()>0){
			model=new LineChartModel();
			for(StatisticBean result : results){
				if(map.containsKey(result.getCompany_nickname())){
					ChartSeries firm=map.get(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_newImage());
				}else{
					ChartSeries firm = new ChartSeries();
					firm.setLabel(result.getCompany_nickname());
					firm.set("Initial", setting.getStartImageForCompanies());
					firm.set(result.getRound_number(), result.getDecres_newImage());
			        map.put(result.getCompany_nickname(), firm);
			        model.addSeries(firm);
				}
			}

			model.setTitle("Image Development");
			model.setLegendPosition("e");
			model.setShowPointLabels(true);
			model.getAxes().put(AxisType.X, new CategoryAxis("Rounds"));
			Axis yAxis = model.getAxis(AxisType.Y);
		    yAxis.setLabel("Image");
	        //Axis yAxis = model.getAxis(AxisType.Y);
	        //yAxis.setMin(0);
	        //yAxis.setMax(10);
		}
		
		return model;
	}
	
	@Override
	public LineChartModel getMarketGameSellingsDevelopment(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameSellingsData(game);
		LineChartModel model = null;
		Map<String,ChartSeries> map=new HashMap<String,ChartSeries>();
		
		if(results.size()>0){
			model=new LineChartModel();
			for(StatisticBean result : results){
				if(map.containsKey(result.getCompany_nickname())){
					ChartSeries firm=map.get(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getAmountCompanyProducts());
				}else{
					ChartSeries firm = new ChartSeries();
					firm.setLabel(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getAmountCompanyProducts());
			        map.put(result.getCompany_nickname(), firm);
			        model.addSeries(firm);
				}
			}
			
			model.setTitle("Sellings Development");
			model.setLegendPosition("e");
			model.setShowPointLabels(true);
			model.getAxes().put(AxisType.X, new CategoryAxis("Rounds"));
			Axis yAxis = model.getAxis(AxisType.Y);
		    yAxis.setLabel("Sellings");
	        //Axis yAxis = model.getAxis(AxisType.Y);
	        //yAxis.setMin(0);
	        //yAxis.setMax(10);
		}
		
		return model;
	}
	
	
	@Override
	public LineChartModel getMarketGameRoundDecisionMarketingInvestment(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameRoundDecisionData(game);
		LineChartModel model = null;
		Map<String,ChartSeries> map=new HashMap<String,ChartSeries>();
		
		if(results.size()>0){
			model=new LineChartModel();
			for(StatisticBean result : results){
				if(map.containsKey(result.getCompany_nickname())){
					ChartSeries firm=map.get(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_marketingInvestment());
				}else{
					ChartSeries firm = new ChartSeries();
					firm.setLabel(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_marketingInvestment());
			        map.put(result.getCompany_nickname(), firm);
			        model.addSeries(firm);
				}
			}

			model.setTitle("Marketing Investment Development");
			model.setLegendPosition("e");
			model.setShowPointLabels(true);
			model.getAxes().put(AxisType.X, new CategoryAxis("Rounds"));
			Axis yAxis = model.getAxis(AxisType.Y);
		    yAxis.setLabel("Money");
	        //Axis yAxis = model.getAxis(AxisType.Y);
	        //yAxis.setMin(0);
	        //yAxis.setMax(10);
		}
		
		return model;
	}
	
	
	@Override
	public LineChartModel getMarketGameRoundDecisionEducationInvestment(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameRoundDecisionData(game);
		LineChartModel model = null;
		Map<String,ChartSeries> map=new HashMap<String,ChartSeries>();
		
		if(results.size()>0){
			model=new LineChartModel();
			for(StatisticBean result : results){
				if(map.containsKey(result.getCompany_nickname())){
					ChartSeries firm=map.get(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_employerEducationInvestment());
				}else{
					ChartSeries firm = new ChartSeries();
					firm.setLabel(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_employerEducationInvestment());
			        map.put(result.getCompany_nickname(), firm);
			        model.addSeries(firm);
				}
			}
			
			model.setTitle("Employer Education Investment Development");
			model.setLegendPosition("e");
			model.setShowPointLabels(true);
			model.getAxes().put(AxisType.X, new CategoryAxis("Rounds"));
			Axis yAxis = model.getAxis(AxisType.Y);
		    yAxis.setLabel("Money");
	        //Axis yAxis = model.getAxis(AxisType.Y);
	        //yAxis.setMin(0);
	        //yAxis.setMax(10);
		}
		return model;
	}
	
	
	@Override
	public LineChartModel getMarketGameRoundDecisionOverdraftCosts(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameRoundDecisionData(game);
		LineChartModel model = null;
		Map<String,ChartSeries> map=new HashMap<String,ChartSeries>();
		
		if(results.size()>0){
			model=new LineChartModel();
			for(StatisticBean result : results){
				if(map.containsKey(result.getCompany_nickname())){
					ChartSeries firm=map.get(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_overdraftCosts());
				}else{
					ChartSeries firm = new ChartSeries();
					firm.setLabel(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_overdraftCosts());
			        map.put(result.getCompany_nickname(), firm);
			        model.addSeries(firm);
				}
			}
			
			model.setTitle("Overdraft Costs Development");
			model.setLegendPosition("e");
			model.setShowPointLabels(true);
			model.getAxes().put(AxisType.X, new CategoryAxis("Rounds"));
			Axis yAxis = model.getAxis(AxisType.Y);
		    yAxis.setLabel("Money");
	        //Axis yAxis = model.getAxis(AxisType.Y);
	        //yAxis.setMin(0);
	        //yAxis.setMax(10);
		}
		return model;
	}
	
	@Override
	public LineChartModel getMarketGameRoundDecisionLogisticCosts(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameRoundDecisionData(game);
		LineChartModel model = null;
		Map<String,ChartSeries> map=new HashMap<String,ChartSeries>();
		
		if(results.size()>0){
			model=new LineChartModel();
			for(StatisticBean result : results){
				if(map.containsKey(result.getCompany_nickname())){
					ChartSeries firm=map.get(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_logisticCosts());
				}else{
					ChartSeries firm = new ChartSeries();
					firm.setLabel(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_logisticCosts());
			        map.put(result.getCompany_nickname(), firm);
			        model.addSeries(firm);
				}
			}
			
			model.setTitle("Logistics Costs Development");
			model.setLegendPosition("e");
			model.setShowPointLabels(true);
			model.getAxes().put(AxisType.X, new CategoryAxis("Rounds"));
			Axis yAxis = model.getAxis(AxisType.Y);
		    yAxis.setLabel("Money");
	        //Axis yAxis = model.getAxis(AxisType.Y);
	        //yAxis.setMin(0);
	        //yAxis.setMax(10);
		}
		return model;
	}
	
	@Override
	public LineChartModel getMarketGameRoundDecisionExpenses(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameRoundDecisionData(game);
		LineChartModel model = null;
		Map<String,ChartSeries> map=new HashMap<String,ChartSeries>();
		
		if(results.size()>0){
			model=new LineChartModel();
			for(StatisticBean result : results){
				if(map.containsKey(result.getCompany_nickname())){
					ChartSeries firm=map.get(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_expenses());
				}else{
					ChartSeries firm = new ChartSeries();
					firm.setLabel(result.getCompany_nickname());
					firm.set(result.getRound_number(), result.getDecres_expenses());
			        map.put(result.getCompany_nickname(), firm);
			        model.addSeries(firm);
				}
			}

			model.setTitle("Product Expenses Development");
			model.setLegendPosition("e");
			model.setShowPointLabels(true);
			model.getAxes().put(AxisType.X, new CategoryAxis("Rounds"));
			Axis yAxis = model.getAxis(AxisType.Y);
		    yAxis.setLabel("Money");
	        //Axis yAxis = model.getAxis(AxisType.Y);
	        //yAxis.setMin(0);
	        //yAxis.setMax(10);
		}
		return model;
	}
	
	
	@Override
	public LineChartModel getMarketPortfolioCostsCurve(Setting setting) {
		LineChartModel model = new LineChartModel();

		ChartSeries series=new ChartSeries();
		series.setLabel("Portfolio Rising for each Company");
		
		//for each Product Amount
		for(int amount=0;amount<10;amount++){
			double costs=CalculationUtil.calculateLogisticCosts(amount, setting);
			series.set(amount, costs);
		}
		
		model.addSeries(series);
		model.setTitle("Portfolio Rising for each Company");
		model.setLegendPosition("e");
		model.setShowPointLabels(true);
		model.getAxes().put(AxisType.X, new CategoryAxis("Products"));
		Axis yAxis = model.getAxis(AxisType.Y);
	    yAxis.setLabel("Money");
	
		return model;
	}
	
	
	@Override
	public void deleteAgentWithAgentTypeId(Integer agentTypeId) {
		agentDao.deleteAgentWithAgentTypeId(agentTypeId);
	}
	

	@Override
	public List<StatisticBean> getMarketGameRoundDecisions(Game game) {	
		return statisticDao.getMarketGameRoundDecisionData(game);
	}

	@Override
	public List<StatisticBean> getAgentRoundInformation(Game game) {
		return statisticDao.getAgentRoundInformation(game);
	}
	
	@Override
	public List<StatisticBean> getMarketGameCompanyProducts(Game game) {
		return statisticDao.getMarketGameCompanyProducts(game);
	}

	@Override
	public List<StatisticBean> getMarketGameProducts() {
		return statisticDao.getMarketGameProducts();
	}

	@Override
	public List<Supplier> getAllSuppliers() {
		return supplierDao.getAll();
	}

	
	@Override
	public List<StatisticBean> getMarketGameAgentTypeSales(Game game) {
		return statisticDao.getMarketGameAgentTypeSales(game);
	}
	
	@Override
	public List<Product> getAllProducts() {
		return productDao.getAll();
	}
	
	@Override
	public List<Product> getAllActiveProducts() {
		return productDao.getAllActive();
	}

	@Override
	public List<News> getLastNewsForGame(Game game, Integer amount) {
		return newsDao.getLastNewsForGame(game, amount);
	}

	@Override
	public HashMap<String, String> getGameDropdown() {
		return gameDao.getGameDropdown();
	}

	@Override
	public HashMap<String, String> getSuppliersDropdown() {
		return supplierDao.getSuppliersDropdown();
	}

	@Override
	public Supplier getSupplierById(Integer id) {
		return this.supplierDao.getById(id);
	}

	@Override
	public Round getRoundById(Integer id) {
		return this.roundDao.getById(id);
	}
	
	@Override
	public List<Agent> getAgentsWithAgentTypeId(Integer agentTypeId){
		return agentDao.getAgentsWithAgentTypeId(agentTypeId);
	}
	
	@Override
	public List<StatisticBean> getMarketGameDecisionsAtRound(Round round) {
		return statisticDao.getMarketGameDecisionsAtRound(round);
	}
	
	@Override
	public void saveInitialization(InitializationBean initBean){
		Setting setting = this.getSetting();
		
		setting.setMaxCostsMarketing(initBean.getMaxMarketing());
		setting.setMaxCostsPersonal(initBean.getMaxPersonal());
		setting.setMaxCostsRD(initBean.getMaxRD());
		setting.setPortfolioExtraCostsPerProduct(initBean.getLogisticCosts());
		setting.setStartBudgetForCompanies(initBean.getStartBudget());
		
		this.settingDao.update(setting);
		
		List<Report> reports = this.reportDao.getAll();
		for(Report report : reports){
			//low
			if(report.getReportType()==1){
				report.setReportPrice(initBean.getReportSmall());
			}else if(report.getReportType()==2){
				report.setReportPrice(initBean.getReportMiddle());
			}else if(report.getReportType()==3){
				report.setReportPrice(initBean.getReportBig());
			}else if(report.getReportType()==4){
				report.setReportPrice(initBean.getReportSpy());
			}
			this.reportDao.update(report);
		}
	}

	@Override
	public CartesianChartModel getMarketGameAgenttypeAmount(Game game) {
		List<StatisticBean> results=statisticDao.getMarketGameAgenttypeAmount(game);
		LineChartModel model = null;
		Map<String,ChartSeries> map=new LinkedHashMap<String,ChartSeries>();
		
		if(results.size()>0){
			model=new LineChartModel();
			for(StatisticBean result : results){
				
				if(map.containsKey(result.getAgType_agentName())){
					ChartSeries agt=map.get(result.getAgType_agentName());
					agt.set(result.getRound_number(),result.getAgType_amount());
				}else{
					ChartSeries agt = new LineChartSeries();
					agt.setLabel(result.getAgType_agentName());
					agt.set(result.getRound_number(),result.getAgType_amount());
			        map.put(result.getAgType_agentName(), agt);
			        model.addSeries(agt);
				}
			}

			model.setTitle("AgentType Amount");
			model.setLegendPosition("e");
			model.setShowPointLabels(true);
			model.getAxes().put(AxisType.X, new CategoryAxis("Rounds"));
			Axis yAxis = model.getAxis(AxisType.Y);
		    yAxis.setLabel("Amount");
	        //Axis yAxis = model.getAxis(AxisType.Y);
	        //yAxis.setMin(0);
	        //yAxis.setMax(10);
		}
		
		return model;
	}
	
}